#include "temu.h"

#define ENTRY_START 0xbfc00000

char *exec_file;
//这里为什么不用 extern ，这样可以引用到吗？
uint8_t *hw_mem;
CPU_state cpu;
CP0_regs cp0;
extern int is_init;
char inst_file_path[100] = "/home/zzzzz/temu/inst.bin";
char data_file_path[100] = "/home/zzzzz/temu/data.bin";

void init_regex();
void init_wp_pool();
void init_ddr3();

int expr_init = 0;
int wp_init = 0;

FILE *log_fp = NULL;


static void init_log() {
	log_fp = fopen("log.txt", "w");
	Assert(log_fp, "Can not open 'log.txt'");
}

static void welcome() {
	printf("Welcome to TEMU!\nThe executable is %s.\nFor help, type \"help\"\n",
			exec_file);
	printf("Dram Addr = %p\n",hw_mem);
}

void init_monitor() {
	/* Perform some global initialization */

	/* Open the log file. */

	init_log();

	/* Compile the regular expressions. */
	init_regex();

	/* Initialize the watchpoint pool. */
	init_wp_pool();

	/* Display welcome message. */
	welcome();
}

static void load_entry() {
	/*
		注意：cpu.pc的初始值是 0xbfc00000，这是一个虚拟地址，对应kseg1,在实际运行的时候，会置
		pc的高三位为0，将其转换为 物理地址
		-------------------------------------------------------------------------------
		+																		+	  +
		+数据																	+ 指令 +
		-------------------------------------------------------------------------------
		 ^ 																		^	  ^ 地址：1fff_ffff最大内存
		地址=0 数据段 														地址:1fc0_0000数据（一开始PC也指向这里）
	*/
	int ret;
    const char *inst_path = inst_file_path;
	//const char *data_path = data_file_path;
	FILE *fp = fopen(inst_path, "rb");

	Assert(fp, "Can not open 'inst.bin'");
	fseek(fp, 0, SEEK_END);
	size_t file_size = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	ret = fread((void *)(hw_mem + (ENTRY_START & 0x1fffffff)), file_size, 1, fp);  // load .text segment to memory address 0x1fc00000 加载 inst.bin 到  0x1fc00000
	assert(ret == 1);

	fp = fopen("/home/zzzzz/temu/data.bin", "rb");
	Assert(fp, "Can not open 'data.bin'");
	fseek(fp, 0, SEEK_END);
	file_size = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	ret = fread((void *)(hw_mem), file_size, 1, fp);			// load .data segment to memory address 0x00000000

	fclose(fp);
}


void restart() {
	/* Perform some initialization to restart a program */

	/* Read the entry code into memory. */
	load_entry();
	//在这里使能中断，但是使能中断不是bootloader干的吗？迷惑
	cp0.status = cp0.status | CP0_STATUS_EXL_MASK;
	
	/* Set the initial instruction pointer. */
	cpu.pc = ENTRY_START;

	/* Initialize DRAM. */
	init_ddr3();
}
